package com.xinyue.game.service.framwork.mapping;


import com.xinyue.game.service.framwork.common.GameFrameworkError;
import com.xinyue.game.service.framwork.common.GameServerException;
import com.xinyue.game.service.framwork.context.GameUserChannelContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 王广帅
 * @date 2021年01月26日 4:35 下午
 */
public class GameHandlerMappingManager {

    private static GameHandlerMappingManager instance = new GameHandlerMappingManager();


    private Logger logger = LoggerFactory.getLogger(GameHandlerMappingManager.class);
    /**
     * 请求uri与对应的请求处理方法的映射
     */
    private Map<String, GameMappingMethod> gameMappingMethodMap = new HashMap<>();

    private GameHandlerMappingManager() {
    }

    public static GameHandlerMappingManager getInstance() {
        return instance;
    }

    /**
     * 从Sring的容器中读取GameHandlerComponent标记的实例
     *
     * @param context
     */
    public void scanGameHandler(ApplicationContext context) {
        String[] handlerBeanNames = context.getBeanNamesForAnnotation(GameHandlerComponent.class);
        logger.debug("----->加载GameHandlerComponent的bean数量:{}", handlerBeanNames.length);
        for (String beanName : handlerBeanNames) {
            Object beanObj = context.getBean(beanName);
            GameHandlerComponent component = beanObj.getClass().getAnnotation(GameHandlerComponent.class);
            //查找处理请求的方法
            Method[] methods = beanObj.getClass().getMethods();
            for (Method method : methods) {
                GameRequestMapping gameMapping = method.getAnnotation(GameRequestMapping.class);
                if (gameMapping != null) {
                    String requestUri = this.getRequestUri(component.value(), gameMapping.requestUri());
                    if (!this.gameMappingMethodMap.containsKey(requestUri)) {
                        GameMappingMethod gameMappingMethod = new GameMappingMethod(beanObj, method);
                        gameMappingMethodMap.put(requestUri, gameMappingMethod);
                    } else {
                        GameMappingMethod gameMappingMethod = this.gameMappingMethodMap.get(requestUri);
                        throw new GameServerException(GameFrameworkError.REQUEST_URI_REPEAT, "requestUri： {} 已存在,处理类：{}，当前处理类：{}", requestUri, gameMappingMethod.getHandlerObj().getClass().getName(), beanObj.getClass().getName());
                    }
                }
            }
        }
    }

    private String getRequestUri(String pre, String value) {
        if (!pre.startsWith("/")) {
            pre = "/" + pre;
        }
        if (!value.startsWith("/")) {
            value = "/" + value;
        }
        String requestUri = pre + value;
        return requestUri;
    }

    public void callMethod(GameUserChannelContext ucx) throws Exception {
        String requestUri = ucx.getHeader().getRequestUri();
        GameMappingMethod gameMappingMethod = gameMappingMethodMap.get(requestUri);
        if (gameMappingMethod == null) {
            throw new GameServerException(GameFrameworkError.REQUEST_NOT_EXIST, "当前请求不存在,requestUri:{}", requestUri);
        }
        Method handlerMethod = gameMappingMethod.getHandlerMethod();
        handlerMethod.invoke(gameMappingMethod.getHandlerObj(), ucx);
    }
}
